package ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import listener.ChatFrameListener;
import listener.ChatListener;
import listener.Listener;
import listener.SocketListener;
import listener.UserListListener;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import protocal.DataPackage;
import protocal.DataPackage.MessageType;
import util.MessageSender;
import util.MessageUtil;
import adapter.UserListAdapter;
import client.ChatClient;

import com.fasterxml.jackson.databind.ObjectMapper;

import data.DataUserList;
import data.User;

public class ChatFrame extends JFrame implements ActionListener{
	
	private static final long serialVersionUID = 1L;
	private final static Logger logger = LogManager.getLogger(ChatFrame.class);
	
	private JTextArea chatTa;
	private JList<String> friendsTa;
	private JTextField sendTf;
	private JButton sendBtn;
	private JButton shakeBtn;
	private volatile boolean active;
	private Listener listener;
	
	public ChatFrame() {
		this.setSize(600, 400);
		this.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		this.setLocationRelativeTo(null);
		init();
		addEvent();
		this.setVisible(false);
		this.setResizable(false);
		active = true;
	}
	
	private void init(){
		this.setLayout(new BorderLayout());
		JPanel panLeft=new JPanel(new BorderLayout());
		JPanel panRight=new JPanel(new BorderLayout());
		JPanel panLeftBottom=new JPanel(new BorderLayout());
		JPanel panBtnGroup=new JPanel(new BorderLayout());
		chatTa=new JTextArea(10,20);
		friendsTa=new JList<>();
		sendTf=new JTextField();
		friendsTa.setSize(100, 400);
		Dimension dimension = new Dimension(100, 400);
		friendsTa.setPreferredSize(dimension);
		sendBtn=new JButton("send");
		shakeBtn=new JButton("shake");
		chatTa.setEditable(false);
		panRight.add(new JScrollPane(friendsTa),BorderLayout.CENTER);
		panLeft.add(new JScrollPane(chatTa), BorderLayout.CENTER);
		panLeft.add(panLeftBottom,BorderLayout.SOUTH);
		this.add(panLeft,BorderLayout.CENTER);
		this.add(panRight,BorderLayout.EAST);
		panBtnGroup.add(shakeBtn,BorderLayout.NORTH);
		panBtnGroup.add(sendBtn,BorderLayout.SOUTH);
		panLeftBottom.add(sendTf,BorderLayout.CENTER);
		panLeftBottom.add(panBtnGroup,BorderLayout.EAST);
		this.setTitle("chat to ALL");
		listener = new ChatFrameListener(this, new ChatListener(chatTa, new UserListListener(friendsTa, new SocketListener())));;
	}
	
	public void loginText(){
		Date date = new Date();
		DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
		String time ="["+User.name+" Online "+dateFormat.format(date)+"]\n";
		chatTa.append(time);
	}
	
	private void addEvent(){
		sendBtn.addActionListener(this);
		friendsTa.addListSelectionListener(new ListSelectionListener() {
			
			@Override
			public void valueChanged(ListSelectionEvent e) {
				
				setTitle("chat to "+friendsTa.getSelectedValue());
			}
		});
		
		shakeBtn.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				DataPackage dataPackage = new DataPackage();
				dataPackage.setFromeName(new User().getName());
				dataPackage.setToName("\\");
				if (friendsTa.getSelectedIndex()!=-1&&friendsTa.getSelectedIndex()!=0) {
					dataPackage.setToName(friendsTa.getSelectedValue());
				}
				dataPackage.setMessageType(MessageType.SHAKE);
				dataPackage.setTime(new Date().getTime());
				MessageSender.send(dataPackage);
				chatTa.append(MessageUtil.buildFromeShake(dataPackage));
			}
		});
		
		this.addWindowListener(new WindowListener() {
		
		@Override
		public void windowOpened(WindowEvent e) {
		}
		
		@Override
		public void windowIconified(WindowEvent e) {
		}
		
		@Override
		public void windowDeiconified(WindowEvent e) {
		}
		
		@Override
		public void windowDeactivated(WindowEvent e) {
		}
		
		@Override
		public void windowClosing(WindowEvent e) {
			 int   option=  JOptionPane.showConfirmDialog(null, "confirm quit? ", "alert ",JOptionPane.YES_NO_OPTION); 
		      if(option==JOptionPane.YES_OPTION){ 
		    	active = false;
				setVisible(false);
				ChatClient.getInstance().close();
				System.exit(0);
		   }
		}
		
		@Override
		public void windowClosed(WindowEvent e) {
		}
		
		@Override
		public void windowActivated(WindowEvent e) {
		}
	});
	}
    
	public void listene(){
		Thread thread =new Thread(new Runnable() {
			@Override
			public void run() {
				ObjectMapper mapper = new ObjectMapper();
				while (active) {
					try {
						BufferedReader reader = ChatClient.getInstance().getReader();
						String data = reader.readLine();
						DataPackage dataPackage =  mapper.readValue(data, DataPackage.class);
						logger.info(dataPackage.toString());
						listener.listen(dataPackage);
						Thread.sleep(10);
					} catch (IOException e) {
						logger.error(e);
						action();
					} catch (InterruptedException e) {
						logger.error(e);
						action();
					}catch (Exception e) {
						logger.error(e);
						action();
					}
				}
				
			}
		});
		thread.start();
	}
	
	private void action(){
		if (active) {
			JOptionPane.showMessageDialog(null, "connect fail", "alert", JOptionPane.ERROR_MESSAGE); 
				active = false;
				setVisible(false);
				ChatClient.getInstance().close();
				System.exit(0);
		   }
	}
	
	public void actionPerformed(ActionEvent e) {
		String content=sendTf.getText();
		if (content.equals("")) {
			JOptionPane.showMessageDialog(null, "you can not send an empty message", "alert", JOptionPane.INFORMATION_MESSAGE); 
			return;
		}
			DataPackage dataPackage = new DataPackage();
			dataPackage.setFromeName(new User().getName());
			dataPackage.setToName("\\");
			if(friendsTa.getSelectedIndex()!=-1&&friendsTa.getSelectedIndex()!=0){
				dataPackage.setToName(friendsTa.getSelectedValue());
			}
			dataPackage.setMessageData(content);
			dataPackage.setMessageType(MessageType.MESSAGE);
			dataPackage.setTime(new Date().getTime());
			MessageSender.send(dataPackage);
			chatTa.append(MessageUtil.buildMessage(dataPackage));
			sendTf.setText("");
	}
	
	public void shake(){
		 int x= this.getX();
		 int y = this.getY();
		 int a = x;
		 int b= y;
		 for (int i = 0; i <10; i++) {
			if ((i&1)==0) {
				x+=10;
				y+=10;
			}else{
				x-=10;
				y-=10;
			}
			this.setLocation(x, y);
			 try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					logger.error(e);
				}
		}
		 this.setLocation(a,b);
	}
	
	public static void main(String[] args) {
		ChatFrame chatFrame = new ChatFrame();
		
		DataUserList userList = DataUserList.getInstance();
		for (int i = 0; i < 30; i++) {
			userList.add("allen"+i);
		}
		UserListAdapter adapter = new UserListAdapter(chatFrame.friendsTa, userList.getUserList());
		adapter.adapter();
		chatFrame.setVisible(true);
		chatFrame.shake();
	}
}
